home *** CD-ROM | disk | FTP | other *** search
/ Danny Amor's Online Library / Danny Amor's Online Library - Volume 1.iso / html / faqs / faq / macintosh / programming-faq < prev    next >
Encoding:
Text File  |  1995-07-25  |  74.2 KB  |  1,828 lines

  1. Subject: The Mac Programming FAQ Answer sheet. [READ ME!]
  2. Newsgroups: comp.sys.mac.programmer,comp.answers,news.answers
  3. From: d88-jwa@mumrik.nada.kth.se (Jon Wätte)
  4. Date: 21 Nov 1994 17:22:51 GMT
  5.  
  6. Archive-name: macintosh/programming-faq 
  7.  
  8. The Public Domain Mac Programming FAQ Answer sheet 2.0
  9. Last update: 941031 ``Octoberfaq''
  10.  
  11. Changes since 940712:
  12. * Total reorg. for improved coherence
  13. * Many small & not-so-small content changes
  14. * Contributors list
  15.  
  16. IMPORTANT NOTE: No FAQ can substitute for real documentation (some of 
  17. which is mentioned in this FAQ) If you ask a question in 
  18. comp.sys.mac.programmer which has a good answer in one of the three 
  19. important sources, you will probably not get an answer.  (Think 
  20. Reference, New Inside Macintosh, Macintosh Technical Notes)
  21.  
  22. This sheet was started by and largely exists due to the efforts of Jon 
  23. Watte, whom you may reach as <h+@nada.kth.se>.  Chris Thomas, whom you 
  24. may reach as <thunderone@delphi.com>, is the current caretaker and 
  25. overall responsible person.  If there is anything you find errant, 
  26. missing or in need of an update, please send Chris your submission and he 
  27. will include it.  All FAQ Answer submissions sent will be considered to 
  28. be in the public domain unless stated otherwise (in which case they will 
  29. not be included in this FAQ sheet).
  30.  
  31. LESS IMPORTANT NOTE: This FAQ has been reorganized to make it easier to 
  32. find and put Qs.  Suggestions and constructive comments are welcome.
  33.  
  34. COMPILER VENDORS - please see question 10.8.  Happiness is a warm 'n' 
  35. fuzzy code generator...  If you have answers for this one, we will be 
  36. very pleased to read them.
  37.  
  38. New submissions should be in the form:
  39. "Q: What question should I answer?
  40.  
  41. A: This one, obviously..."
  42. if you want to definitely see the submission in the next edition.  
  43. Otherwise integration may take a bit longer.
  44.  
  45. This sheet is currently archived on nada.kth.se where you can reach it 
  46. using afs as /afs/nada.kth.se/public/ftp/pub/hacks/mac-f aq/CSMP_PD_FAQ 
  47. or using anonymous FTP (GIVE YOUR E-MAIL ADDRESS AS PASSWORD!) as 
  48. pub/hacks/mac-faq/CSMP_PD_FAQ You can also find it on rtfm.mit.edu unedr 
  49. the name macintosh/programming-faq.  But that's not all! It should be 
  50. available in the Delphi ICONtact Developer SIG [go com mac dev da info 
  51. narrow faq dir], and most likely AOL's Mac Development area [Keyword: 
  52. MDV] as well.
  53.  
  54. This sheet is now posted once a week to the appropriate news groups.  I 
  55. have also started adding mail addresses for vendors mentioned in the 
  56. FAQ; mail me if you're mentioned and feel neglected!
  57.  
  58. This sheet is divided into several parts; each of which covers a general 
  59. area which often gets asked about in the Internet newsgroup 
  60. comp.sys.mac.programmer.  Please download a copy of this answer sheet and 
  61. search it before you post to the 'net, to help reduce bandwidth.
  62.  
  63. There is NO or VERY LIMITED error checking in these code examples, FOR 
  64. BREVITY ONLY.  You should make sure you ALWAYS check ALL return codes, 
  65. and handle any that you are not prepared to deal with appropriately.
  66.  
  67. Current topics:
  68. (search for *number* to find a topic quickly)
  69.  
  70.  1) Development Tools
  71.          what you need to get started, tool-specific issues
  72.  2) Memory
  73.          handles, large arrays, resource handles
  74.  3) User Interfacing
  75.          menus, windows, events, multitasking
  76.  4) Files
  77.          Mac fopen, wdrefnums, getting the full pathname of files
  78.  5) Imaging
  79.          QuickDraw and how to avoid it
  80.  6) Text
  81.          Text editing packages and the limits thereof
  82.  7) Communications and Networking
  83.          Serial ports, TCP/IP, sockets
  84.  8) Interapplication Communication
  85.          AppleEvents and OSA
  86.  9) Dynamic Linking
  87.          external code resources
  88. 10) Compatibility
  89.          gestalt, glue
  90. 11) Optional System Software
  91.          1. QuickTime
  92.            codec details and the lack thereof
  93. 12) Third-Party Solutions
  94.          databases
  95. 13) Dessert
  96.          yummies the Macintosh way
  97. 14) Contributors
  98.          whodunnit?
  99.  
  100. *1* Development and debugging tools for the Macintosh 
  101.  
  102. 1.1) Q: What do I need to start writing Macintosh software? 
  103.  
  104. [this section needs serious rewriting, any volunteers are welcome]
  105.  
  106. A1:
  107. 1. A development environment.
  108. 2. A project.
  109. 3. Smart Friends (tm).
  110.  
  111. What I mean by numbers 2 and 3 is:
  112. 2. Something that _you_ have a personal interest in getting running.
  113. Something to keep you going through those periods of frustration and
  114. fatigue.  Just working through the exercises in a book won't cut it.
  115.  
  116. 3. People who are at least 2 weeks farther along than you, that can help
  117. you avoid the petty (and not-so-petty) wastes of time that await the
  118. neophyte.  These people should preferably be easy to contact (i.e. a local
  119. phone call) and have the same approximate sleep patterns.
  120.  
  121. A2: A Mac, a lot of time, and a few hundred $.  Although you can develop 
  122. software on a Classic-type machine, it is not to be attempted by the 
  123. weak of heart or stressed of time.  If you're doing paid work and/or 
  124. work for a company, a Quadra-class machine or Centris 650 or better is 
  125. almost a must; remember that your time costs your employer much more 
  126. than just your salary.  8 MB is a minimum to run at all comfortably, and 
  127. Virtual Memory is not suited for development work.  Similarly; if you 
  128. don't have at least 80 MB free on your hard disk you need to buy more 
  129. space.
  130.  
  131. You need a development system such as Think C, CodeWarrior C++, MPW C or 
  132. Prograph, you need at least some of the New Inside Mac books (Toolbox 
  133. Essentials, Files, Memory come to mind) and a good entry-level 
  134. third-party book may help.
  135.  
  136. Once you are up to speed on the general layout of the Mac and its 
  137. toolboxes, you should call APDA and order the monthly developer mailing, 
  138. which will give you a CD chock full of documentation, utilities and 
  139. system software once a month.  You will also, obviously, need a CD 
  140. player; one of which Apple's own CD300 is a very good buy at the time of 
  141. writing this.  If you don't have the dough for the monthly mailing 
  142. ($250/year) you can order a _develop_ subscription; this quarterly 
  143. magazine ($30-$50/year) comes with a CD containing most Inside Mac 
  144. documentation.  <apda@appplelink.apple.com>
  145.  
  146. If you don't know how to program, go learn your language of choice 
  147. BEFORE attempting a "real" Mac application.  Programming is a discipline 
  148. often requiring different thought processes than your normal day job.  A 
  149. beginning book, like Lippman: The C++ Primer, or Sydow: Think THINK C 
  150. might help (the latter uses the Think C compiler, while the former can 
  151. be used with any C++ compiler)
  152.  
  153. Another tool which many find a must-have is the Think Reference version 
  154. 2.0.1, containing reference material on the most used parts of the Mac 
  155. toolbox with lightning-fast look-up and mostly correct usage hints and 
  156. code snippets.  It does not cover the newest system additions, nor the 
  157. modern "universal" headers format, though.
  158.  
  159. 1.2) Q: What is the most used Macintosh development system? 
  160.  
  161. A: Out of products on the market, I have no idea; both MPW and Think 
  162. products appear to be used.  Lately, CodeWarrior has come out of nowhere 
  163. and grabbed a large share of the market visibility because they have the 
  164. fastest compiler and they generate PowerPC code as well as 68K code.  
  165. Among hobbyists, the Think products from Symantec are most popular 
  166. because of the low price, and steep educational discounts, and, of 
  167. course, the easily approachable interface! However, now that CodeWarrior 
  168. is available at $59-$99 educational price; anything can happen.
  169.  
  170. The Think C linker only strips dead code on a FILE level basis (and this 
  171. is when you turn on "Smart Linking") The MPW linker (of no specified IQ, 
  172. as someone so eloquently put it :-) strips dead code by the function, as 
  173. does CodeWarrior.  That may be part of the reason the Think C linker is 
  174. ten times faster than the MPW linker - but then how do you explain the 
  175. CodeWarrior linker, which links like the MPW linker, but at speeds 
  176. approaching Think C?
  177.  
  178. In the beginning, the Mac was programmed using Mc68000 assembly or 
  179. Pascal; this was reflected in the Old Inside Mac volumes which only gave 
  180. Pascal-style and assembly-style interfaces to the Mac toolbox.  These 
  181. days, Apple tells us to use C or even better C++ for developing new 
  182. applications, as that will speed up the transition to PowerPC and also 
  183. coming cross-platform efforts.  (Language Systems have a Pascal for 
  184. PowerPC product now, but I don't know about pricing or quality)
  185.  
  186. There are also at least two Fortran compilers, at least three SmallTalk 
  187. implementations (ObjectWorks, SmallTalk/V and SmallTalkAgents), a 
  188. world-class LISP/CLOS implementation (Macintosh Common Lisp 2.0) that 
  189. seems to have died, and others.  There are ways of stripping SmallTalk 
  190. apps so they're smaller and faster as standalone apps than in the 
  191. environment.
  192.  
  193. Metrowerks have a Pascal and a C and C++ compiler for both 68k and Power 
  194. Macs; the package with the three of them is called "CodeWarrior."
  195.  
  196. CSI has MacForth, of which I only know the name and someone who says 
  197. it's pretty good.
  198.  
  199. There is another good Common Lisp implementation: Procyon Common Lisp.  
  200. I don't know if it is actively supported, but Procyon CL is also 
  201. available for DOS, OS/2 and Windows (as Allegro CL/PC) and actively 
  202. developed.
  203.  
  204. 1.3) Q: Where do I find a public domain C compiler for the Mac. 
  205. Is there a GCC for the mac? What about the FSF boycott of Apple 
  206. products? 
  207.  
  208. A: There is no really good solution for a "for-free" C development 
  209. system for the Mac.  GCC has been ported, but requires the MPW shell and 
  210. MPW assembler to run; these have to be bought from APDA.  There is a 
  211. standalone port of GCC 1.37 on nic.switch.ch:software/mac/src/think_c.  
  212. There was a freely available C compiler called Harvest C, which was 
  213. somewhat unstable but usable for smaller programs; it was abandoned by 
  214. the original author Eric W Sink because of a lack of time and later 
  215. taken up by the TopSoft project.
  216.  
  217. The FSF boycott of Apple products means they will not talk to you if you 
  218. ask them for help in doing a Mac port, and they will not incorporate 
  219. your changes into their main code base.  However, they still allow 
  220. others to port GNU stuff to the Mac, and it has been done with most of 
  221. the application-like GNU programs (bison, flex, perl (not really part of 
  222. GNU), ...)
  223.  
  224. gcc-1.37r14 V1.1 standalone is available for ftp at nic.switch.ch: 
  225. software/mac/src/think_c.
  226.  
  227. A fairly stable port of GCC 2.3.3 to MPW is available for ftp at 
  228. atg.apple.com [anyone know the directory?].
  229.  
  230. For those whose main interest is in developing only text based C/C++ 
  231. programs, using GCC under MacMiNT might be appropriate.  MacMiNT is a 
  232. UNIX like operating system ported from the Atari ST which supports many 
  233. freely available UNIX utilities like GCC, GDB, make, tcsh, byacc, perl, 
  234. and more.  MacMiNT stuff can be found at on nic.switch.ch in 
  235. 'software/mac/src/macmint'.
  236.  
  237. 1.4) Q: Are there any other free Mac development platforms? 
  238.  
  239. A: Yerk and Mops.  These are object oriented languages based on the old 
  240. product Neon which itself was based on Forth.  They are available with 
  241. Manuals at oddjob.uchicago.edu (anonymous FTP).
  242.  
  243. Plus, there's MacGambit, MacScheme, xlisp, and MacMETH which is the 
  244. actual ETH (read: Nick Wirth's group) Modula 2, all for free via FTP.  
  245. Also available is MacOberon and MacOberon system/3 betas.
  246.  
  247. And OpenProlog.  And SIOD (Scheme in One Defun) And [mail in more if you 
  248. dare [and please do include ftp addresses if ya would]]
  249.  
  250. 1.5) Q: What's the difference between the MPW, Think and CodeWarrior 
  251. environments?
  252.  
  253. A: The main difference is that Think and CodeWarrior are integrated 
  254. environments, while MPW provides you with a command-line shell for your 
  255. Mac and tools to use in it.  MPW also has a slightly higher systems 
  256. demand and a much slower linker.
  257.  
  258. The good thing about MPW is that you can write scripts and make files to 
  259. do anything you want in the way you want it.  Think or CW still don't 
  260. have a viable solution to do a build that requires more than one link 
  261. operation, or has more than one destination file.
  262.  
  263. For the MPW environment, there are three source level debuggers; SADE, 
  264. SourceBug and Voodoo Monkey.  The latter is an experimental debugger 
  265. with support for threads debugging; the middle is bundled with MPW while 
  266. SADE has to be bought separately (but is fully scriptable in its own 
  267. scripting language)
  268.  
  269. The Think environments have their own integrated debuggers; the Think 
  270. Pascal one has a lot of useful features while the Think C/C++ one is a 
  271. little more basic (but is gaining in functionality with each release) 
  272. Stepping through source code and looking at variables is generally 
  273. faster and easier in Think than the MPW debuggers.
  274.  
  275. Metrowerks has their own debugger which works like the MPW debuggers; i 
  276. e it runs the application standalone and pokes at it from the outside, 
  277. while the Think debuggers run the application "wrapped" in a special 
  278. environment, making for some subtle interferences with your heap (which 
  279. you usually don't notice)
  280.  
  281. CodeWarrior is by far the fastest compiler; it can compile to 68k code 
  282. on a Power Macintosh for really fast compiles.  Symantec C++ (a k a 
  283. "Think C++") is the most complete C++.  MPW has the most powerful 
  284. environment.
  285.  
  286. Any commercial Mac developer should have all three of CodeWarrior, Think 
  287. and MPW of whatever language they prefer (Pascal, C or C++), though some 
  288. people seem to be able to get by with just CodeWarrior and MPW.
  289.  
  290. 1.6) Q: What is a good low-level debugger for the Mac? 
  291.  
  292. A: MacsBug is freely available for ftp from ftp.apple.com; log in as 
  293. user anonymous and give your FULL e-mail address as password.  MacsBug 
  294. is your basic monitor-type debugger that takes a few hundred Ks of 
  295. memory, and lets you break, step, disassemble, look at the stack etc of 
  296. most anything running on your Mac.  Since it's free (it's also on the 
  297. developer CDs) and provides most of the functionality you need, this is 
  298. a popular choice.
  299.  
  300. TMON is another debugger which sports a more mac-like interface; it 
  301. provides windows and uses the mouse.  It can take as little or much 
  302. memory as you want by excluding or including certain areas of 
  303. functionality.  A nice touch is the 6502 disassembler that you can use 
  304. to de-bug the code the IOP processors run on the Mac IIfx and Quadra 
  305. 900/950.
  306.  
  307. Jasik Designs have a debugger called The Debugger which can do both low- 
  308. and high-level debugging, with or without source and for all types of 
  309. code, application, code resources, everything.  This is the debugger of 
  310. choice for many large developers because of its high power and many 
  311. features not found anywhere else.  However; newcomers beware! This is 
  312. the Lamborghini of debuggers; if you know how to drive it, it is the 
  313. fastest way from A to B; if you don't, you'll just end up in the ditch.  
  314. As a lady put it: "The man wouldn't know a user interface if it bit him 
  315. in the rear."
  316.  
  317. 1.7) Q: Are there any visual developments environments for the 
  318. Mac (comparable to Visual C++)?
  319.  
  320. A: There is no Visual C++ as such.  However, there is a C++ 
  321. parser/editor called ObjectMaster which provides good browsing and 
  322. editing capabilities if you already have a C++ compiler.  Think C++ also 
  323. comes with a browser built-in, and you can draw dialogs/windows using 
  324. plain old ResEdit, even for your custom view types.
  325.  
  326. Symantec C++ 7.0 also bundles a view editor/code generator called Visual 
  327. Architect; it is fairly complete and has a good level of integration 
  328. into the Think Project Manager.
  329.  
  330. AppMaker is a GUI builder/code generator.  Granted, it's not as nice as 
  331. VC++, but it's quite a product in any case.
  332.  
  333. MarksMan version 3.0 has totally revised TCL templates, and now 
  334. generates well-thought-out TCL code.  It can also generate ANSI C code 
  335. etc.
  336.  
  337. Also, Neuron Data has their UI tool called Open Interface, which is 
  338. better than VC++ and creates code portable across 35 platforms.  
  339. Unfortunately it's $2500 per developer per platform.  There's also two 
  340. other cross-platform products called XVT and Galaxy, the former has 
  341. gotten flak on UseNet while the latter reportedly is the premier 
  342. cross-platform application builder framework; with everything from 
  343. styled text to network support.
  344.  
  345. There is a fully visual, dynamic, object oriented data-flow-driven 
  346. programming language for the Mac called Prograph Corporate Programming 
  347. Something-or-other (CPX).  It is expensive ($1500) but offers a built-in 
  348. database, easy interfaces to existing data bases, very high productivity 
  349. in implement-test-debug cycling and also offers cross-platform 
  350. capabilities (it comes with a class library which, when your code is 
  351. written using it, works under Windows after re-compilation)
  352.  
  353. SmalltalkAgents comes with a GUI builder, which lets you draw your
  354. interface, and then outputs the code for you.
  355.  
  356. If you'd rather do Common Lisp, Macintosh Common Lisp offers a Common 
  357. Lisp Object System with support for most Mac interface items; you can 
  358. edit code while it is running and build stand-alone applications.
  359.  
  360. However, all of these tools generate rather larger binaries with larger 
  361. system demands than a program written in C.  On the other hand; C++ 
  362. programs require more memory and disk space than programs written in 
  363. assembly.  It's a trade-off, and I believe this type of tools is the 
  364. wave of the near future.
  365.  
  366. 1.8) Q: What class libraries are there for the Mac? 
  367.  
  368. A: Apart from the libraries mentioned above, there are three contenders: 
  369. MacApp, TCL, and PowerPlant.  "Bedrock" will never be released as a 
  370. product, although parts of it surface in TCL 2.0 and other parts will be 
  371. the base for the OpenDoc Parts Framework.
  372.  
  373. MacApp is a heavy-duty class library that has tons of features and a 
  374. steep learning curve; it runs under MPW with Pascal or C++, and also 
  375. under Think Pascal 4.0 A major application written in MacApp is 
  376. PhotoShop.
  377.  
  378. TCL stands for Think Class Library and comes with Think Pascal, C or 
  379. C++.  It is a smaller library that still fills most peoples needs; since 
  380. Think C implements a subset of C++ (the most important OO concepts such 
  381. as virtual functions and inheritance) and the TCL is carefully written 
  382. not to take advantage of any C++ features not in Think C, you can use it 
  383. with Think C.  A major application written in TCL is Lotus 1-2-3.  (TCL 
  384. 1.1.3) Starting with Symantec C++ 7.0, Think Class Library 2.0 using 
  385. templates and "real" C++ objects is shipping.
  386.  
  387. PowerPlant is the Metrowerks CodeWarrior offering; it's written by the 
  388. guy who designed the Think Class Library, but it has a lot of 
  389. differences from the original TCL; for one, it's not a monolithic one 
  390. base class framework.  On the other hand, it has some catching up to do 
  391. before it reaches the level of MacApp.  It is gaining quite fast on TCL, 
  392. but isn't all there yet.
  393.  
  394.  
  395. 1.9) Q: How should I debug and test my software? 
  396.  
  397. A: Get ahold of, and install, the extensions DoubleTrouble, 
  398. DisposeResource and EvenBetterBusError.  They will catch 80% of any 
  399. memory related bugs you may have, including many bugs that follow NULL 
  400. handles or pointers.
  401.  
  402. A low-level debugger is required, and while you install it, install the 
  403. "leaks" dcmd which will help you catch memory leaks in your application.  
  404. All of these tools are available from ftp.apple.com.
  405.  
  406. 1.10) Q: Are there any good Mac programming magazines?
  407.  
  408. A: One Mac programming magazine I know of is MacTech Magazine (formerly 
  409. MacTutor).  It covers a variety of Mac programming topics on various 
  410. levels.  Operating independently from Apple, it has a lot of stuff for 
  411. the beginning Mac programmer, as well as occasional nuggets for the more 
  412. experienced of us.  <custservice@xplain.com>
  413.  
  414. Another VERY GOOD Magazine is _develop_ which is put out by Apple four 
  415. times a year; it comes with a CD containing code for all articles ever 
  416. published in _develop_, and a lot of documentation and system software 
  417. freebies as well.  $30/year in the US.  <dev.subs@applelink.apple.com>
  418.  
  419. 1.11) Q: What about protected memory? I'm sick and tired of re-booting 
  420. when my application crashes.
  421.  
  422. A: Write better software! 
  423.  
  424. Or install The Debugger from Jasik Designs, which can provide your 
  425. application with write-protection of critical parts of memory.  This may 
  426. only work for 030 Macs, though.
  427.  
  428. Making the Mac OS memory-protected is tricky, because applications expect 
  429. to be able to write to low memory, the system heap, temporary memory, 
  430. window lists, and even each other's heaps in some interapplication 
  431. communication solutions that date back to before AppleEvents and the PPC 
  432. Toolbox.
  433.  
  434. 1.12) Q: I have this library written in (Think) Pascal that I want to use 
  435. from Think C/Symantec C, but I get link errors/don't know how to do it.  
  436. What should I do?
  437.  
  438. A: Start by writing a .h file describing the interface.  Remember to 
  439. declare the Pascal functions "pascal".  Build a library with Think Pascal 
  440. and convert it with oConv.
  441.  
  442. Do you get link errors on symbols defined in your Pascal lib? Check the 
  443. capitalisation used.
  444.  
  445. Do you get errors on symbols like LMUL and LDIV? Those functions are 
  446. defined in the Think Pascal library Runtime.lib or uRuntime.lib.  Include 
  447. uRuntime.lib and try again.
  448.  
  449. Do you get link errors on standard symbols like thePort? This is due to 
  450. bad capitalization in Symantec's libs.  Run oConv with .v checked.  This 
  451. will create a TEXT file with a .v extension.  Open that with a text 
  452. editor and correct the capitalization.  Run oConv again, with .v checked 
  453. this time too.
  454.  
  455. Do you still get errors on standard symbols? Are you using Think 
  456. C/Symantec C++ version 6 or higher? Then you must open the library (after 
  457. converting it) from Think C version *5*, and remove the unit named 
  458. %_TOOLBOX.  (If I'm not mistaken, this is the toolbox init unit, which 
  459. you won't need anyway.)
  460.  
  461. *2* Memory
  462.  
  463. 2.1) Q: What is a handle? 
  464.  
  465. A: A handle is a pointer to a pointer to something.  However, it is more 
  466. than that; creating a handle by taking the address of one of your own 
  467. pointers does NOT create a Handle; the Memory Manager will only deal 
  468. properly with Handles that are created using NewHandle or something that 
  469. calls it (such as NewRgn or GetResource)
  470.  
  471. 2.2) Q: When do I have to lock a Handle? 
  472.  
  473. A: The contents of a Handle may move, and when it does, the pointer your 
  474. handle is pointing to is changed to point to the new address so your 
  475. handle is always valid.  The toolbox may call the memory manager to 
  476. allocate more memory pretty much anytime you call it (the toolbox) and 
  477. when memory is allocated, your handle may move in memory.  Don't 
  478. dereference a handle into a pointer (or take the address of a field in a 
  479. record a handle is double-pointing to) and then call the toolbox and 
  480. expect the pointer to still be valid.  The only way to ensure that the 
  481. pointer will still be valid is to call HLock on the handle to lock it.
  482.  
  483. Use HGetState and HSetState to save & restore the "locked" state of a 
  484. handle when you lock it.
  485.  
  486. 2.3) Q: How do I dispose of Handles? 
  487.  
  488. A: DisposeHandle (formerly called DisposHandle) once and ONLY once will 
  489. do the trick.  Trying to dispose of an already disposed Handle is an 
  490. error.  DoubleTrouble (see above) will catch such bugs when they do 
  491. occur.
  492.  
  493. 2.4) Q: What about resources? 
  494.  
  495. A: Calling GetResource returns NULL if the resource is not found or 
  496. there is not enough memory, else it returns a handle to the resource.  
  497. This handle may be moved or locked like any other handle, but DO NOT 
  498. call DisposeHandle to get rid of a resource handle - call 
  499. ReleaseResource.  DisposeResource (see above) will catch this kind of 
  500. bug.
  501.  
  502. Remember that AddResource makes a resource handle out of an ordinary 
  503. handle, and RmveResource or DetachResource makes an ordinary handle out 
  504. of a resource handle.  You cannot call AddResource with a resource 
  505. handle; you have to DetachResource it first.
  506.  
  507. Resource handles are automagically disposed when the resource file they 
  508. belong to is closed.
  509.  
  510. 2.5) Q: I'm trying to use a largish array in Think C, but get a "code 
  511. overflow" error.  This is valid C, why doesn't it work?
  512.  
  513. A: The ANSI standard does not guarantee that any structure larger than 
  514. 32767 bytes be correctly handled.  Because of historical constraints, 
  515. the Mac memory model is built around several small blocks of size 32K or 
  516. less; these are used both for code and global/static data.  If you want 
  517. to use more code or data, you have to turn on "far code" or "far data" - 
  518. you still will not get around the restriction of 32K code or data per 
  519. compiled file, though.
  520.  
  521. This is one area where CodeWarrior shines; it works around most such 
  522. limitations and it doesn't cost much in performance either!
  523.  
  524. As opposed to, say, DOS or Windows, however, you can allocate as much 
  525. memory as you want (and there is in the machine) and step through it 
  526. using ordinary pointers; it's just that global and static data space is 
  527. addressed off the A5 register using a 16bit displacement addressing mode 
  528. in the 68000 processor.
  529.  
  530. On the PowerPC, everything is 32bit from the start; that runtime model 
  531. is much more like UNIX because it's taken from IBMs AIX.  No limitations 
  532. there.
  533.  
  534. *3* User interaction and You
  535.  
  536. 3.1) Q: How do I read the modifier keys of the keyboard? 
  537.  
  538. A: Just call EventAvail and check the event.modifiers field. 
  539. Only works when you are in the foreground. You can also use 
  540. GetKeys(), or (as a last resort) check the lo-mem global KeyMap 
  541. directly. 
  542.  
  543. 3.2) Q: How do I move the mouse cursor to a specific position?
  544.  
  545. A: Wait! Don't do it! There has to be a better way!
  546.  
  547. If you feel you HAVE to do it (for a game or VERY special simulation 
  548. situation) you can use the Cursor Device Manager documented in the tech 
  549. notes on ftp.apple.com.  If that manager is not installed, as it's not 
  550. on older Macs, you can use the following code:
  551.  
  552. you need to have some low-memory globals defined.  they may be defined 
  553. in SysEqu.h.
  554.  
  555. #define MTemp 0x828
  556. #define RawMouse 0x82c
  557. #define CrsrNewCouple 0x8ce
  558.  
  559. note that CrsrNewCouple is actually a combination of two globals, just 
  560. to make our life slightly easier.
  561.  
  562. the code i use to move the mouse is:
  563.  
  564. *code*
  565. void
  566. MoveMouseTo ( Point where ) {
  567.  
  568.         HideCursor ( ) ;
  569.         * ( Point * ) RawMouse = where ;
  570.         * ( Point * ) MTemp = where ;
  571.         * ( short * ) CrsrNewCouple = -1 ;
  572.         ShowCursor ( ) ;
  573. }
  574. *end*
  575.  
  576. you need to hit a couple more global variables if you want this to work 
  577. properly in a multiple-monitor system, but i forget what they are 
  578. offhand.  poke through SysEqu.h, and you should be able to figure it out 
  579. without a problem.
  580.  
  581. On the PowerPC, these lo-mem globals may not be available for native 
  582. applications; however, all Power Macintoshes implement the Cursor Device 
  583. Manager.  All Macs made after March '93 (including Centris 650 and 610) 
  584. implement the Cursor Device Manager, in fact.
  585.  
  586. There is also a file on nada.kth.se:pub/hacks/mac-faq/MoveMouse.c which 
  587. shows how to use the Cursor Device Manager, written by an excellent 
  588. Apple engineer.  Grab!
  589.  
  590. 3.3) Q: My menus don't show up in the menu bar
  591.  
  592. A: If your menus are hiearchical, you'll have to install them manually; 
  593. GetNewMBar won't do it for you.  See also 15.2.
  594.  
  595. 3.4) Q: When the user selects my menus, I get strange results back; they 
  596. seem to have different menu IDs than my menus?
  597.  
  598. A: The Menu ID as used by the menu manager is NOT the same thing as the 
  599. MENU resource ID (used in the MBAR resource and with GetMenu()) When you 
  600. create a MENU, ResEdit sets the menu ID to the MENU resource ID, but if 
  601. you re-number the resource, you will have to open the menu in ResEdit 
  602. and change the menu ID using the "Edit MENU ID" menu item.
  603.  
  604. 3.5) Q: I use GetMenu() to find a menu in the menu bar, and then change 
  605. it, but it seems I have a memory leak OR my changes don't "punch 
  606. through"
  607.  
  608. A: GetMenu() is only intended if you don't already have the menu "in 
  609. memory." The call you should use almost all the time is GetMHandle() 
  610. which gets the handle to a menu in the current menu bar by its menu ID 
  611. (not resource id)
  612.  
  613. 3.6) Q: What about pre-emptive multitasking? 
  614.  
  615. A: To the user, the Mac multitasking method, which builds upon each 
  616. application calling WaitNextEvent, GetNextEvent or EventAvail every so 
  617. often and the Process Manager/MultiFinder switching applications only at 
  618. such calls, is at least as good as preemtive multitasking, because the 
  619. present system priotitizes user interface responsiveness over everything 
  620. else.  The only shortfall about this is formatting floppies, which locks 
  621. up the Mac CPU.  This is because the Mac floppy controller is really 
  622. stupid, and would happen even if the Mac multitasked preemptively.
  623.  
  624. There IS "real" pre-emptive multitasking available for use in Mac 
  625. applications; the expensive way is buying A/UX 3.0 which can have Mac 
  626. applications written as UNIX processes; the cheap way is installing the 
  627. Thread Manager which will allow you to create pre-emptive threads.  
  628. However, the restrictions on those threads are the same as those on Time 
  629. Manager tasks: don't call any function in an unloaded segment, and don't 
  630. call QuickDraw or any toolbox call which may move memory (which are most 
  631. ToolBox calls; paradoxally, BlockMove is safe :-) as are, surprisingly, 
  632. FSRead and FSWrite)
  633.  
  634. There are several problems with making the Mac OS preemptive; including 
  635. apps that draw outside their windows or directly to screen, user dragging 
  636. and other issues.  The system is being reimplemented for 8.0 to solve 
  637. these problems.
  638.  
  639. *4* Files
  640.  
  641. 4.1) Q: How do I tell fopen() to open a file the user has selected using 
  642. StandardGetFile?
  643.  
  644. A: The "standard" ANSI C file functions are less than well suited for 
  645. the Macintosh way of doing things.  However, if you are doing a port for 
  646. your own enjoyment and benefit (or maybe for in-house work) you can use 
  647. the following function: (see below about converting a wdRefNum into a 
  648. vRefNum/parID pair)
  649.  
  650. *code*
  651. FILE *
  652. fopen_mac ( short vRefNum , long parID , char * fileName , char * mode ) {
  653.  
  654. short oldVol ;
  655. short aVol ;
  656. long aDir , aProc ;
  657. FILE * ret = NULL ;
  658.  
  659.         if ( GetVol ( NULL , & oldVol ) ) {
  660.                 return NULL ;
  661.         }
  662.         if ( GetWDInfo ( oldVol , & aVol , & aDir , & aProc ) ) {
  663.                 return NULL  ;
  664.         }
  665.         if ( HSetVol ( NULL , vRefNum , parID ) ) {
  666.                 return NULL ;
  667.         }
  668.         ret = fopen ( fileName , mode ) ;
  669.         if ( HSetVol ( NULL, aVol , aDir ) ) {
  670.                 /* an error we can't currently handle */
  671.         }
  672.         if ( SetVol ( NULL, oldVol ) ) {
  673.                 /* an error we can't currently handle */
  674.         }
  675.         return ret ;
  676. }
  677. *end*
  678.  
  679. All of the above is necessary for one reason or another - if you are 
  680. interested, by all means look HSetVol up in Think Reference 2.0 or New 
  681. Inside Mac: Files.
  682.  
  683. In older versions of MPW; this wouldn't work since the MPW libraries 
  684. used to do a GetVol and explicitly use that value by itself.
  685.  
  686. 4.2) Q: When can I use the HOpen, HCreate etc file calls? Are they only 
  687. System 7 calls?
  688.  
  689. A: All the HXxx calls that take a vRefNum and parID as well as the file 
  690. name are implemented in glue that works on any system that has HFS 
  691. (meaning 3.2 and up with the HD20 INIT, and all systems from System 6 
  692. and up)
  693.  
  694. The glue is available in MPW 3.2 and up, and Think C 5.0 and up.  This 
  695. goes for all HXxx calls except HOpenDF; therefore, if you are interested 
  696. in System 6 compatibility, use HOpen instead and make sure you don't 
  697. allow file names beginning with a period.
  698.  
  699. 4.3) Q: Why do you say wdRefNum sometimes and vRefNum sometimes? 
  700. Why do you say parID sometimes and dirID sometimes? 
  701.  
  702. A: When the Mac first made an appearance in 1984, it identified files by 
  703. using a vRefNum (volume reference number meaning a floppy disk or later 
  704. hard disk) and a name.  Once HFS saw the light of day, folders within 
  705. folders became a reality, and you needed a dirID as well to point out 
  706. what folder you really meant on the volume.  However, older programs 
  707. that weren't being rewritten still knew nothing about directory IDs, so 
  708. Apple had SFGetFile make up "fake" vRefNums that didn't just specify a 
  709. volume, but also a parent folder.  These are called wdRefNums (for 
  710. working directory) and were a necessary evil invented in 1985.  You 
  711. should not create (or, indeed, use) wdRefNums yourself.
  712.  
  713. There is a system-wide table that maps wdRefNums onto vRefNum/parID 
  714. pairs.  There is a limit to the size of this table.  A dirID and a parID 
  715. is almost the same thing; you say "parID" when you mean the folder 
  716. something is in, while you say a "dirID" when you mean the folder 
  717. itself.  If you for instance have a folder called "Foo" with a folder 
  718. called "Bar" in it, the parID for "Bar" would be the dirID for "Foo."
  719.  
  720. 4.4) Q: How do I convert a wdRefNum as returned by SFGetFile 
  721. into a vRefNum/parID pair to use with the HXxx calls?
  722.  
  723. A: Use GetWDInfo, which is declared as: 
  724.  
  725. Pascal OSErr GetWDInfo ( short wdRefNum , short * vRefNum , long * parID 
  726. , OSType * procID ) ;
  727.  
  728. The procID parameter must be non-NULL and point to an OSType variable, 
  729. but the value of that variable can and should be ignored.
  730.  
  731. It is recommended that, as soon as you get your hands on a wdRefNum, for 
  732. instance from SFGetFile, you directly convert it into a vRefNum/parID 
  733. pair and always use the latter to reference the folder.
  734.  
  735. 4.5) Q: How do I select a folder using SFGetFile? 
  736.  
  737. A: This requires a custom dialog with a filter proc.  It is too 
  738. complicated to show here, but not totally impossible to comprehend.  
  739. There is sample code on ftp.apple.com, in the directory dts/snippets, on 
  740. how to do this.
  741.  
  742. 4.6) Q: How do I get the full path of a file referenced by a vRefNum, 
  743. parID and name?
  744.  
  745. A: You don't. 
  746.  
  747. OK, I cheated you.  There is exactly ONE valid reason to get the full 
  748. path of a file (or folder, for that matter) and that is to display its 
  749. location to the user in, say, a settings dialog.  To actually save the 
  750. location of the file you should do this: (assuming the file is in an 
  751. FSSpec called theFile - you can use FSSpecs in your program even if you 
  752. don't run under System 7; just make your own MyFSMakeFSSpec that fills 
  753. in the FSSpec manually if it's not implemented)
  754.  
  755. *code*
  756. if ( ! aliasManagerAvailable ) { /* System 6 ? */
  757.         GetVolumeName ( theFile -> vRefNum , vName ) ;
  758.         GetVolumeModDate ( vRefNum , & date ) ;
  759.         Save ( vName , date , parID , fileName ) ;
  760. } else {
  761.         NewAlias ( NULL , theFile , & theAlias ) ;
  762.         Save ( theAlias ) ;
  763.         DisposeHandle ( ( Handle ) theAlias ) ;
  764. }
  765. *end*
  766.  
  767. If you are really concerned about these issues (of course you are!) you 
  768. should save BOTH of these methods when available, and load back whatever 
  769. is there that you can handle; since users may be using your application 
  770. in a mixed System 6/System 7 environment.
  771.  
  772. To get back to the file is left as an exercise for the reader. 
  773.  
  774. To open a file using fopen() or the Pascal equivalent, see above about 
  775. using and not using HSetVol.
  776.  
  777. 4.7) Q: What about actually getting the full path for a file? I promise 
  778. I will only use it to show the location of a file to the user!
  779.  
  780. A: Enter PBGetCatInfo, the Vegimatic of the Mac file system.  Any Mac 
  781. hacker of knowledge has taken this system call to his heart.  What you 
  782. do is this:
  783.  
  784. *code*
  785. OSErr
  786. GetFolderParent ( FSSpec * fss , FSSpec * parent ) {
  787.  
  788. CInfoPBRec rec ;
  789. short err ;
  790.  
  791.         * parent = * fss ;
  792.         rec . hFileInfo . ioNamePtr = parent -> name ;
  793.         rec . hFileInfo . ioVRefNum = parent -> vRefNum ;
  794.         rec . hFileInfo . ioDirID = parent -> parID ;
  795.         if ( parent -> name [ 0 ] ) {
  796.                 rec . hFileInfo . ioFDirIndex = 0 ;
  797.         } else {
  798.                 rec . hFileInfo . ioFDirIndex = -1 ;
  799.         }
  800.         rec . hFileInfo . ioFVersNum = 0 ;
  801.         err = PBGetCatInfoSync ( & rec ) ;
  802.         if ( ! ( rec . hFileInfo . ioFlAttrib & 0x10 ) ) { /* Not a folder */
  803.                 if ( ! err ) {
  804.                         err = dirNFErr ;
  805.                 }
  806.         } else {
  807.                 parent -> parID = rec . dirInfo . ioDrParID ;
  808.                 parent -> name [ 0 ] = 0 ;
  809.         }
  810.         return err ;
  811. }
  812.  
  813.  
  814. OSErr
  815. GetFullPathHandle ( FSSpec * fss , Handle * h ) {
  816.  
  817. Handle  tempH = NULL ;
  818. short err ;
  819. FSSpec fs = * fss ;
  820.  
  821.         while ( fs . parID > 1 ) {
  822.                 tempH = NULL ;
  823.                 PtrToHand ( & fs . name [ 1 ] , & tempH , fs . name [ 0 ] ) ;
  824.                 PtrAndHand ( ( void * ) ":" , tempH , 1 ) ;
  825.                 HandAndHand ( * h , tempH ) ;
  826.                 SetHandleSize ( * h , 0L ) ;
  827.                 HandAndHand ( tempH , * h ) ;
  828.                 DisposeHandle ( tempH ) ;
  829.                 tempH = NULL ; 
  830.                 GetFolderParent ( & fs , & sSpec ) ;
  831.                 fs = sSpec ;
  832.         }
  833.         GetVolName ( fs . vRefNum , fs . name ) ;
  834.         PtrToHand ( & fs . name [ 1 ] , & tempH , fs . name [ 0 ] ) ;
  835.         PtrAndHand ( ( void * ) ":" , tempH , 1 ) ;
  836.         HandAndHand ( * h , tempH ) ;
  837.         SetHandleSize ( * h , 0L ) ;
  838.         HandAndHand ( tempH , * h ) ;
  839.         DisposeHandle ( tempH ) ;
  840.         tempH = NULL ;
  841.         if ( ! IsFolder ( fss ) ) {
  842.         SetHandleSize ( * h , GetHandleSize ( * h ) - 1 ) ; // Remove colon }
  843.         return 0 ;
  844. }
  845. *end*
  846.  
  847. 4.8) Q: So how do I get the names of the files in a directory? 
  848.  
  849. A: You use PBGetCatInfo again, but this time you set ioFDirIndex to 1 or 
  850. more (you need to know the dirID and vRefNum of the
  851.  
  852. folder you're interested in) You then call PBGetCatInfoSync for values 
  853. of ioFDirIndex from 1 and up, until you get an fnfErr.  Any other err 
  854. means you are not allowed to get info about THAT item, but you may be 
  855. for the next.  Then collect the names in the string you made ioNamePtr 
  856. point to as you go along.  Note that you need to fill in the ioDirID 
  857. field for each iteration through the loop, and preferrably clear the 
  858. ioFVersNum as well.
  859.  
  860. Note that the contents of a directory may very well change while you are 
  861. iterating over it; this is most likely on a file server that more than 
  862. one user uses, or under System 7 where you run Personal File Share.
  863.  
  864. 4.9) Q: How do I find the name of a folder for which I only know the 
  865. dirID and vRefNum?
  866.  
  867. A: You call (surprise!) PBGetCatInfo! Make ioNamePtr point to an empty 
  868. string (but NOT NULL) of length 63 (like, an Str63) and ioFDirIndex 
  869. negative (-1 is a given winner) - this makes PBGetCatInfo return 
  870. information about the vRefNum/dirID folder instead of the file/folder 
  871. specified by vRefNum, parID and name.
  872.  
  873. 4.10) Q: How do I make the Finder see a new file that I created? Or if I 
  874. changed the type of it; how do I display a new icon for it?
  875.  
  876. A: You call (surprise!) PBGetCatInfo followed by PBSetCatInfo for the 
  877. FOLDER the file is in.  Inbetween, you should set ioDrMdDat to the 
  878. current date&time.  Code:
  879.  
  880. *code*
  881. OSErr
  882. TouchFolder ( short vRefNum , long parID ) {
  883.  
  884. CInfoPBRec rec ;
  885. Str63 name ;
  886. short err ;
  887.  
  888.         rec . hFileInfo . ioNamePtr = name ;
  889.         name [ 0 ] = 0 ;
  890.         rec . hFileInfo . ioVRefNum = vRefNum ;
  891.         rec . hFileInfo . ioDirID = parID ;
  892.         rec . hFileInfo . ioFDirIndex = -1 ;
  893.         rec . hFileInfo . ioFVersNum = 0 ;
  894.         err = PBGetCatInfoSync ( & rec ) ;
  895.         if ( err ) {
  896.                 return err ;
  897.         }
  898.         GetDateTime ( & rec . dirInfo . ioDrMdDat ) ;
  899.         rec . hFileInfo . ioVRefNum = vRefNum ;
  900.         rec . hFileInfo . ioDirID = parID ;
  901.         rec . hFileInfo . ioFDirIndex = -1 ;
  902.         rec . hFileInfo . ioFVersNum = 0 ;
  903.         rec . hFileInfo . ioNamePtr [ 0 ] = 0 ;
  904.         err = PBSetCatInfoSync ( & rec ) ;
  905.         return err ;
  906. }
  907. *end*
  908.  
  909. 4.11) Q: Aren't we done with PBGetCatInfo soon? 
  910.  
  911. A: Well, it turns out that you can also find out whether an FSSpec is a 
  912. file or a folder by calling PBGetCatInfo and check bit 4 (0x10) of 
  913. ioFlAttr to see whether it is a folder.  You may prefer to call 
  914. ResolveAliasFile for this instead.
  915.  
  916. You can also check the script of the file's title using PBGetCatInfo and 
  917. check the ioFlFndrXInfo field if you want to work with other script 
  918. systems than the Roman system.
  919.  
  920. Another common use is to find out how many items are in a folder; the 
  921. modification date of something or the correct capitalization of its name 
  922. (since the Mac file system is case independent BUT preserves the case 
  923. the user uses)
  924.  
  925. 4.12) Q: How do I set what folder should initially be shown in the 
  926. SFGetFile boxes?
  927.  
  928. A: You stuff the dirID you want to show into the lo-mem global 
  929. CurDirStore, and the NEGATIVE of the vRefNum you want into the lo-mem 
  930. global SFSaveDisk.
  931.  
  932. If you are using CustomGetFile and return sfSelectionChanged from an 
  933. "init" message handler, you must remember to clear the script code, else 
  934. the selection will not change.
  935.  
  936. 4.13) Q: How do I find the folder my application started from? How do I 
  937. find the application file that's running?
  938.  
  939. A: Under System 7, you call GetProcessInformation using the 
  940. ProcessSerialNumber kCurrentProcess with a pointer to an existing FSSpec 
  941. in the parameter block.  This will give you your file, and, by using the 
  942. vRefNum and parID, the folder the application is in.
  943.  
  944. *code*
  945. OSErr   CurrentProcessLocation(FSSpec *applicationSpec)
  946. {
  947.         ProcessSerialNumber currentPSN;
  948.         ProcessInfoRec info;
  949.         
  950.         currentPSN.highLongOfPSN = 0;
  951.         currentPSN.lowLongOfPSN = kCurrentProcess;
  952.         info.processInfoLength = sizeof(ProcessInfoRec);
  953.         info.processName = NULL;
  954.         info.processAppSpec = applicationSpec;
  955.         return ( GetProcessInformation(¤tPSN, &info) );
  956. }
  957. *end*
  958.  
  959. Beware from writing to your applications resource or data forks; the 
  960. former breaks on CDs/write protected floppies/file servers/virus 
  961. checkers, the latter fails on PowerPC as well as in the above cases.
  962.  
  963.  
  964. *5* Imaging with QuickDraw and the Gang
  965.  
  966. 5.1) Q: Why is CopyBits so slow? 
  967.  
  968. A: It is not.  It just requires some hand-holding to get good results.  
  969. The main rules are: Make sure the source and destination pixMaps are of 
  970. the same depth.
  971.  
  972. Make sure the front color is black and the back color is white.
  973.  
  974. Use srcCopy and don't use a masking region. 
  975.  
  976. Copy to an unclipped window (the frontmost window).  Make sure the 
  977. ctSeed values of the source pixMap and dest pixMap match. 
  978.  
  979. Copying few and large pixMaps is faster than copying many and small 
  980. ones.  Icon-sized sprites count as small ones.
  981.  
  982. Make sure your source bitmap or pixelMap has the same alignment, when 
  983. adjusted for the source and destination rect expressed in global screen 
  984. coordinates.  The necessary alignment is 32 bits (4 bytes), although 128 
  985. bit (16 byte) alignment is probably even better on 68040 macs and won't 
  986. hurt on other macs.
  987.  
  988. Example of global alignment: 
  989.  
  990. Your window is positioned at (42,100) (H,V) 
  991.  
  992. Your destination rectangle is (10,20)-(74,52) 
  993.  
  994. The alignment coefficient of the rectangle in global coordinates is 
  995. (42+10)*bitDepth where bitDepth is one of 1,2,4,8,16 or 32.
  996.  
  997. Make sure your source pixmap rect has the same coeffecient modulo your 
  998. alignment factor (in bits) For black&white macs, this is still true, 
  999. although bitDepth is fix at 1.  Offscreen pixMaps can calculate with a 
  1000. "global posistion" of 0,0 and get correct results.
  1001.  
  1002. 5.2) Q: Why is CopyBits still too slow? 
  1003.  
  1004. A: Because there is always some overhead involved in calling QuickDraw; 
  1005. you have the trap dispatcher, clipping checks, and checking whether the 
  1006. CopyBits call is being recorded in a PICT handle (if you called 
  1007. OpenPicture)
  1008.  
  1009. If you can't live with this, look at 4.8 below, but PLEASE try and make 
  1010. CopyBits work, and retain the CopyBits code in your application, so 
  1011. users with special monitors (accellerator cards, PowerBook color 
  1012. screens, Radius Pivot screens) can still play your game.  (non-game 
  1013. applications don't need more speed than CopyBits can give at its max.  
  1014. Promise!)
  1015.  
  1016. 5.3) Q: What is the fastest way to set one pixel? 
  1017.  
  1018. A: NOT SetCPixel()! Assuming you have the correct ForeColor() set, you 
  1019. can set the pen size to (1,0) and call Line (0,1)
  1020.  
  1021. I have heard PaintRect is good for this but requires slightly more code.  
  1022. Using PaintRect eliminates a trap call.
  1023.  
  1024. 5.4) Q: Why do pictures I record suddenly draw as empty space or not 
  1025. draw at all?
  1026.  
  1027. A: When recording pictures, you have to set the clipping area to exactly 
  1028. the frame of the picture you are recording.  This is because it is 
  1029. initally set at -32768,32727 in both directions, and offsetting the 
  1030. picture even one pixel when drawing it will result in the region 
  1031. wrapping around and becoming empty.
  1032.  
  1033. When recording pictures, do this: 
  1034.  
  1035. *code*
  1036. PicHandle h = OpenPicture ( & theRect ) ;
  1037. ClipRect ( & theRect ) ;
  1038.         /* draw the picture */
  1039. ClosePicture ( ) ;
  1040. *end*
  1041.  
  1042. 5.5) Q: Where can I find the format of picture files and 
  1043. resources? 
  1044.  
  1045. A: The format of a picture resource version 1 is defined in a 
  1046. technical note. This format is obsolete. 
  1047.  
  1048. The format of a picture resource version 2 is defined in Old Inside Mac 
  1049. vol V, with addenda in Old Inside Mac vol VI.
  1050.  
  1051. Some things happen with QuickTime compressed pictures; try the Inside 
  1052. Mac: QuickTime book or turn to Inside Mac: Imaging with QuickDraw which 
  1053. is the definite reference on QuickDraw.
  1054.  
  1055. The format of a picture file is the same as that of a picture resource 
  1056. with 512 added 0 bytes in front.
  1057.  
  1058. 5.6) Q: GWorlds? 
  1059.  
  1060. A: What about them? They're great.  Look them up in Old Inside Mac vol 
  1061. VI.  Don't forget to SetGWorld back to what it was before calling 
  1062. WaitNextEvent.
  1063.  
  1064. 5.7) Q: How do I find the current depth of the screen? 
  1065.  
  1066. A: My question to you is: What screen? Many macs have more than one 
  1067. screen attached.  You can use GetDeviceList and walk the devices to find 
  1068. the screen you're looking for (use TestDeviceAttribute to see whether 
  1069. it's a screen) or you can call GetMaxDevice() to find the deepest device 
  1070. your window intersects.
  1071.  
  1072. Once you have the device handle, finding the depth is just a 
  1073. matter of looking at the gdPMap pixMapHandle, and dereference it 
  1074. to the pmSize field. Done. 
  1075.  
  1076. 5.8) Q: Why is it a bad idea to draw directly to screen? 
  1077.  
  1078. A: Because of several reasons: 
  1079.  
  1080. - You will be incompatible with future display hardware. 
  1081.  
  1082. - You will be incompatible with some present-day display 
  1083. hardware, such as Radius Pivots and PowerBook color screens. 
  1084.  
  1085. - You have to think about a lot of things; testing it all on 
  1086. your own machine is not possible and the chances of crashing are 
  1087. great. 
  1088.  
  1089. - You will be incompatible with future hardware where devices 
  1090. may live in some unaccessible I/O space. 
  1091.  
  1092. 5.9) Q: But I really need to do it. I can't make my animation 
  1093. into a QuickTime movie, and CopyBits is too slow, even when 
  1094. syncing to the screen retrace. 
  1095.  
  1096. A: You have to prepare yourself, and ask these questions: 
  1097.  
  1098. 1) Do I want to support all screens, or just 8-bit devices? 
  1099.  
  1100. 2) Do I have a few weeks of free time to make it work? 
  1101.  
  1102. 3) Do I want to get nasty mail when I break on some hardware and 
  1103. have to rev the application - even if I may not be able to get 
  1104. ahold of the hardware that makes it break? 
  1105.  
  1106. If all you're doing is rendering an image pixel-by-pixel or 
  1107. line-by-line, maybe you can draw directly into an offscreen 
  1108. pixMap/GWorld and then CopyBits the entire GWorld to screen? 
  1109. That will be more compatible, especially if you use the 
  1110. keepLocal flag when creating the GWorld. 
  1111.  
  1112. 5.10) Q: Okay, so how do I get the base address of the screen? 
  1113.  
  1114. A: "The" screen? Which screen? There may be several. The base 
  1115. address may be on an accellerated screen card. There may be more 
  1116. than one screen covering the same desktop area. 
  1117.  
  1118. Due to unfortunate circumstances, there is a bug in 
  1119. GetPixBaseAddr() that causes it to return incorrect results for 
  1120. early versions of System 7. Instead, get the baseAddr directly 
  1121. from the gdPMap handle of the GDHandle for the screen you draw 
  1122. to. This address may need switching to 32bit mode to be valid. 
  1123.  
  1124. 5.11) Q: Quit stalling and give me code! 
  1125.  
  1126. A: Okay, but I'll let you sweat over Inside Mac to figure out 
  1127. what it does. All of it is important; believe me! To make this 
  1128. code run faster, a lot of the things it does can be done once 
  1129. before starting to draw. 
  1130.  
  1131. Make sure that you have a window that covers the area where you 
  1132. are drawing, so other windows will not be overdrawn. Also make 
  1133. sure that you do not do direct-to-screen-drawing while you are 
  1134. in the background. 
  1135.  
  1136. *code*
  1137. /* This is presently untested code */
  1138. /* Value is dependent on what depth the screen has */
  1139. /* This code doesn't work on non-color-quickdraw Macs (i e the MacClassic) */
  1140. /* "where" is in GLOBAL coordinates */
  1141. void
  1142. SetPixel ( Point where , unsigned long value ) {
  1143.  
  1144. Rect r ;
  1145. GDHandle theGD ;
  1146. char * ptr ;
  1147. long rowBytes ;
  1148. short bitsPerPixel ;
  1149. PixMapHandle pmh ;
  1150. Boolean oldMode ;
  1151.  
  1152.         r . left = where . h ;
  1153.         r . top = where . v ;
  1154.         r . right = r . left + 1 ;
  1155.         r . bottom = r . top + 1 ;
  1156.         theGD = GetMaxDevice ( & r ) ;
  1157.         if ( theGD ) {
  1158.                 where . v -= ( * theGD ) -> gdRect . left ;
  1159.                 where . h -= ( * theGD ) -> gdRect . top ;
  1160.                 pmh = ( * theGD ) -> gdPMap ;
  1161.                 rowBytes = ( ( * pmh ) -> rowBytes ) & 0x3fff ;
  1162.                 ptr = ( char * ) ( * pmh ) -> baseAddr ;
  1163.                 bitsPerPixel = ( * pmh ) -> pixelSize ;
  1164.                 oldMode = true32b ;
  1165.                 ptr += where . v * rowBytes ;
  1166.                 SwapMMUMode ( & oldMode ) ;
  1167.                 switch ( bitsPerPixel ) {
  1168.                 case 1 :
  1169.                         if ( value & 1 ) { 
  1170.                                 ptr [ where . h >> 3 ] |= ( 128 >> ( where . h & 7 ) ) ;
  1171.                         } else {
  1172.                                 ptr [ where . h >> 3 ] &= ~( 128 >> ( where . h & 7 ) ) ;
  1173.                         }
  1174.                         break ;
  1175.                 case 2 :
  1176.                         ptr [ where . h >> 2 ] &= ( 192 >> 2 * ( where . h & 3 ) ) ;
  1177.                         ptr [ where . h >> 2 ] |= ( value & 3 ) << 2 * ( 3 - ( where . h & 3 ) ) ;
  1178.                         break ;
  1179.                 case 4 :
  1180.                         ptr [ where . h >> 1 ] &= ( where . h & 1 ) ? 0xf : 0xf0 ;
  1181.                         ptr [ where . h >> 1 ] |= ( value & 15 ) << 4 * ( 1 - ( where . h & 1 ) ) ;
  1182.                         break ;
  1183.                 case 8 :
  1184.                         ptr [ where . h ] = value ;
  1185.                         break ;
  1186.                 case 16 :
  1187.                         ( ( unsigned short * ) ptr ) [ where . h ] = value ;
  1188.                         break ;
  1189.                 case 32 :
  1190.                         ( ( unsigned long * ) ptr ) [ where . h ] = value ;
  1191.                         break ;
  1192.                 default :
  1193.                         abort ( ) ; /* Should never get here */
  1194.                 }
  1195.                 SwapMMUMode ( & oldMode ) ;
  1196.         }
  1197. }
  1198. *end*
  1199.  
  1200. *6* Text
  1201.  
  1202. 6.1) Q: How do I get TextEdit to display more than 32k of text?
  1203.  
  1204. A: You don't.  Truly, it's not worth it.  There's a call-for-call 
  1205. TextEdit replacement called TE32k which does > 32k text, and is 
  1206. available from any recent Info-Mac mirror.  It doesn't do styled text, 
  1207. though.
  1208.  
  1209. 6.2) Q: How do I get TextEdit to display more than 32k of __styled__ 
  1210. text *and* embedded objects in the text (such as pictures)?
  1211.  
  1212. WASTE, available at ftp://ghost.dsi.unimi.it/pub2/papers/piovanel, is a 
  1213. vast improvement over TextEdit.  Version 1.0 does >32k styled text 
  1214. retains compatibility with the TextEdit style scrap (which is used to 
  1215. store styled text in files such as SimpleText's, as well as in the 
  1216. clipboard), includes source code and is freeware.  Really worth the 
  1217. download.  Version 1.1 adds embedded objects within the text, such as 
  1218. pictures, intelligent cut-and-paste, built-in Drag Manager support.  1.1 
  1219. is currently in alpha, but seems to be very stable.
  1220.  
  1221. 6.3) Q: How do I include pictures in text using TextEdit?
  1222.  
  1223. A: There's no really easy way (such as a TEAddPict() call), and it will 
  1224. be a nasty looking kludge if you do get it working, but if you can live 
  1225. with that, here's how to do it.  I do recommend that you take a look 
  1226. at Q 6.2, above.
  1227.  
  1228. Write an algorithm to get the position of a special marker character 
  1229. [Teach/SimpleText uses option-space] or text attribute that the user 
  1230. will insert wherever he wants a picture.  Pass this position to a 
  1231. function similar to the one below.
  1232.  
  1233. *code* 
  1234. /*
  1235.         TEDrawPicture
  1236.         Draw a picture within TextEdit's text.
  1237.         
  1238.         input:
  1239.                 pos - the position of the special character in the text where the user 
  1240.                                 wants a picture.
  1241.                 r       - size of picture
  1242.         
  1243.         output:
  1244.                 r       - frame in which picture was drawn
  1245. */
  1246.  
  1247. void TEDrawPicture(short pos,PicHandle pic,Rect &r,TEHandle theTE)
  1248. {
  1249.         Point   bottomLeft;     //could be topleft, or whatever you want
  1250.         
  1251.         bottomLeft=TEGetPoint(pos,theTE);
  1252.         
  1253.         r.right=bottomLeft.h+(r.right-r.left);
  1254.         r.top=bottomLeft.v-(r.bottom-r.top);
  1255.         r.left=bottomLeft.h;
  1256.         r.bottom=bottomLeft.v;
  1257.         
  1258.         DrawPicture(pic,&r);
  1259. }
  1260.  
  1261. *end*
  1262.  
  1263. I'll leave selection and hiliting as an exercise for the reader.
  1264.  
  1265. Thereotically, it should be possible to kludge up TextEdit to the point 
  1266. where it would treat pictures as if they were actually letters (rather big 
  1267. letters, but letters just the same).  That's what the width and word break 
  1268. hooks are for, after all.  However, this would be a lot of Work, and I've 
  1269. never seen it done.  One is lead to believe that it's less work to create 
  1270. an improved version of TextEdit from the ground up with picture support.  
  1271. One could probably modify WASTE for this purpose, since the source is 
  1272. available.
  1273.  
  1274. 6.4) Q: I have all this money, and I want to get rid of it. How do I
  1275. edit more than 32k of styled text now?
  1276.  
  1277. A: There are at least two solutions.
  1278.  
  1279. 1) The Galaxy application framework comes with a styled text editting
  1280. engine which does more than 32k of text. It also happens to support
  1281. cross-platform application development. Pricing starts at $10000.
  1282. <galaxy@visix.com>
  1283.  
  1284. 2) DataPak has a library called "PAIGE" in the works, and you can
  1285. buy a late beta of it. It is written to be customizable to any extent,
  1286. and you can do _anything_ in it (want quicktime movies that play and
  1287. flow with the text while editting? Three pages of code; you can adapt
  1288. their picture sample code.) Available for Mac, Windows and Power Mac.
  1289. Pricing at $5000 ($25000 for source code) - it might be cheaper if
  1290. you talk to them.
  1291.  
  1292. *7* Communications and Networking
  1293.  
  1294. 7.1) Q: How do I get at the serial ports? 
  1295.  
  1296. A: You call OpenDriver for the names "\p.AOut" and "\p.AIn" to get at 
  1297. the modem port, and "\p.BOut" and "\p.BIn" for the printer port.  The 
  1298. function RAMSDOpen was designed for the original Mac with 128 kB of 
  1299. memory and 64 kB of ROM, and has been extinct for several years.
  1300.  
  1301. However, many users use their serial ports for MIDI, LocalTalk, graphic 
  1302. tablets, or what have you and have installed an additional serial port 
  1303. card to get more ports.  What you SHOULD do as a good application is to 
  1304. use the Comm Toolbox Resource Manager to search for serial resources; 
  1305. this requires that the Comms Toolbox is present (true on earlier System 
  1306. 6 with an INIT, on later System 6 and System 7 always, as well as on 
  1307. A/UX) and that you have initialized the comms resource manager.  The 
  1308. exact code follows (adapted from Inside Mac Comms Toolbox):
  1309.  
  1310. *code*
  1311. #include <CommResources.h>
  1312. OSErr
  1313. FindPorts ( Handle * portOutNames , Handle * portInNames , Handle * names , Handle * iconHandles ) {
  1314.  
  1315. OSErr ret = noErr ;
  1316. short old = 0 ;
  1317. CRMRec theCRMRec , * found ;
  1318. CRMSerialRecord * serial ;
  1319.  
  1320.         * portOutNames = NewHandle ( 0L ) ;
  1321.         * portInNames = NewHandle ( 0L ) ;
  1322.         * names = NewHandle ( 0L ) ;
  1323.         * iconHandles = NewHandle ( 0L ) ;
  1324.         while ( ! ret ) {
  1325.                 theCRMRec . crmDeviceType = crmSerialDevice ;
  1326.                 theCRMRec . crmDeviceID = old ;
  1327.                 found = ( CRMRec * ) CRMSearch ( ( QElementPtr ) & theCRMRec ) ;
  1328.                 if ( found ) {
  1329.                         serial = ( CRMSerialRecord * ) found -> crmAttributes ;
  1330.                         old = found -> crmDeviceID ;
  1331.                         PtrAndHand ( & serial -> outputDriverName , * portOutNames ,
  1332.                                 sizeof ( serial -> outputDriverName ) ) ;
  1333.                         PtrAndHand ( & serial -> inputDriverName , * portInNames ,
  1334.                                 sizeof ( serial -> inputDriverName ) ) ;
  1335.                         PtrAndHand ( & serial -> name , * names , 
  1336.                                 sizeof ( serial -> name ) ) ;
  1337.                         PtrAndHand ( & serial -> deviceIcon , * iconHandles ,
  1338.                                 sizeof ( serial -> deviceIcon ) ) ;
  1339.                 } else {
  1340.                         break ;
  1341.                 }
  1342.         }
  1343.         return err ;
  1344. }
  1345. *end*
  1346.  
  1347. This will create four handles with the driver names, device names and 
  1348. driver icon handles for all of the available serial devices.  Then let 
  1349. the user choose with a pop-up menu or scrolling list, and save the 
  1350. choice in your settings file.
  1351.  
  1352. You can use OpenDriver, SetReset, SetHShake, SetSetBuf, SerGetBuf and 
  1353. the other Serial Manager functions on these drivers.  To write to the 
  1354. serial port, use FSWrite for synchronous writes that wait until all is 
  1355. written, or PBWrite asynchronously for queuing up data that is supposed 
  1356. to go out but you don't want to wait for it.  At least once each time 
  1357. through your event loop, you should call SerGetBuf on the in driver 
  1358. reference number you got from OpenDriver, and call FSRead for that many 
  1359. bytes - neither more nor less.
  1360.  
  1361. If you are REALLY interested in doing the right thing, you will use the 
  1362. Communications Toolbox Connection Manager instead; this will give you 
  1363. access to modems, direct lines, and networks of various kinds using the 
  1364. same API! Great for stuff like BBSes that may be on a network as well 
  1365. etc.  The Comms Toolbox also priovides modularized terminal emulation 
  1366. and file transfer tools, although the Apple-suplied VT102 tool is pretty 
  1367. lame, as is the VT102 mode of the VT320 tool.
  1368.  
  1369. 7.2) Q: Where is a Berkley sockets library for the Mac? 
  1370.  
  1371. A: There are some problems with that.  MacTCP, the Mac Toolbox 
  1372. implementation of TCP/IP, doesn't have an API that looks at all like 
  1373. Berkley sockets.  For instance, there is ONE paramater-block call to do 
  1374. a combined listen()/accept()/bind() - sort of.  I have heard that there 
  1375. may be a socket library available by ftp from MIT but haven't seen it 
  1376. myself.
  1377.  
  1378. There is also a pretty good C++ TCP implementation called GUSI which is 
  1379. easily handled, and it also is callable from C using the Berkley socket 
  1380. API.  Apart from TCP, it also handles "standard" Mac network protocols 
  1381. such as ADSP.  The big disadvantage is that it is currently only 
  1382. implemented for MPW.  The ftp site is nic.switch.ch, 
  1383. software/mac/src/mpw_c.
  1384.  
  1385. I can also recommend the Communications Toolbox; for the price of using 
  1386. an API that is a bigger pain in the ass than using Windoze, you get the 
  1387. benefit of being able to use any kind of connection (TCP tools are 
  1388. available).
  1389.  
  1390. Novell and Wollogong offer commercial socket-like libraries. 
  1391.  
  1392. 7.3) Q: Where do I find MacTCP? 
  1393.  
  1394. A: You can buy the MacTCP developers kit from APDA.  It is also 
  1395. available on E T O, and if you want saner headers than those, try ftp to 
  1396. seeding.apple.com.  MacTCP (the control panel) is included with System 
  1397. 7.5 and above.
  1398.  
  1399. 7.4) Q: I'm trying to write to the serial port.  It works fine on the 
  1400. following Machines, Quadra700, IIFX, Powerbook 170, Quadra 840av, but 
  1401. freezes on the Duo 230 and 280c.
  1402.  
  1403. A: You need to call SerHShake.  Otherwise you get screwed on some 
  1404. machines without a hardware handshaking cable because the port default to 
  1405. hardware handshaking.
  1406.  
  1407. *8* IAC
  1408.  
  1409. 8.1) Q: What are AppleEvents? 
  1410.  
  1411. A: AppleEvents are a level-5 network protocol.  If you are not familiar 
  1412. with the ISO network stack, this means it's a way of structuring sessions 
  1413. between network entities (programs) that is not dependent on the 
  1414. underlying protocol (such as PPC or TCP/IP) Despite being a network 
  1415. protocol, they can be very useful on Macs that are not on a network.  In 
  1416. short, they provide applications with a comprehensive way to send 
  1417. arbitrary structured data to other applications (or themselves) which 
  1418. receive the events through their main event loop.
  1419.  
  1420. The AppleEvent Object Model is a way of looking at applications and the 
  1421. data they contain, and also a level-6 network protocol.  You _can_ send 
  1422. AppleEvent Object Model data through AppleEvents (and the standard 
  1423. AppleEvents defined in the AppleEvent Registry use it) but you don't have 
  1424. to - unless you want to talk with other applications, of course, then the 
  1425. AEOM is a lingua franca.
  1426.  
  1427. 8.2) Q: What are the four required AppleEvents? 
  1428.  
  1429. A: There are four events your application really must implement if you 
  1430. want to sell it: the kCoreEventClass class, kAEOpenApplication, 
  1431. kAEQuitApplication, kAEOpenDocuments and kAEPrintDocuments events IDs.  
  1432. When you support these events (or any AppleEvents) you will not get 
  1433. startup info through GetAppParams() anymore, unless you run under System 
  1434. 6 of course.  The kAEOpenApplication event will be sent to you when the 
  1435. user double-clicks your app and it's not started yet.  When receiving it, 
  1436. you can put up a new untitled window.
  1437.  
  1438. kAEOpenDocuments is sent when the user double-clicks your apps documents.  
  1439. Note that if the first AppleEvent you receive is a kAEOpenDocuments 
  1440. event, the user started your app by double-clicking its documents.
  1441.  
  1442. kAEPrintDocuments is sent when the user selects your documents and 
  1443. chooses "Print" in the Finder menu.  If this is the first AppleEvent you 
  1444. receive, you should print the documents and then quit the application 
  1445. again; if you received a kAEOpenApplication or kAEOpenDocuments event 
  1446. before this, you should just print the documents and close them when 
  1447. you're done.
  1448.  
  1449. kAEQuitApplication is sent to you when the user chooses "Shutdown" or 
  1450. "Restart" from the Apple Menu.  You should ask the user whether he wants 
  1451. to save any unsaved changed documents, and then quit unless the user 
  1452. presses Cancel.
  1453.  
  1454. Interestingly enough, you can use these four AppleEvents to send even to 
  1455. non-AE-aware applications, and the system will translate these events 
  1456. into fake menu selections for you.
  1457.  
  1458. A good way of shutting down the Finder is to send it a Quit AppleEvent.  
  1459. You should send a Quit AppleEvent to File Sharing Extension before you 
  1460. shut down the Finder, though; the FSE is found by looking for a process 
  1461. with the creator 'hhgg'.
  1462.  
  1463. 8.3) Q: Are there any limits or tradeoffs with AppleEvents? 
  1464.  
  1465. A: As always, more power means more responsibility. 
  1466.  
  1467. AppleEvents sent to applications on other Macs require authentification 
  1468. the first time they are sent.  If the remote Mac allows Guests to link to 
  1469. programs, the INIT AutoGuest 2.0 might help (or the code solution that 
  1470. comes with it and you can build into your application)
  1471.  
  1472. In the first version of the AppleEvent manager, there was a total 64K 
  1473. limit on the size of data and overhead.  This limit has been lifted with 
  1474. the version of the AppleEvent manager that comes with AppleScript.
  1475.  
  1476. AppleEvents require a lot of memory copying and handle resizing in their 
  1477. construction; this means that large AppleEvents may be slow in 
  1478. construction, especially when compared to a pure PPC Toolbox or 
  1479. ADSP/ASDSP link.
  1480.  
  1481. You should use your own application signature as event class for 
  1482. AppleEvents you make up, in order not to collide with anybody else.  
  1483. Other than that, you are free to make your own events for your own needs, 
  1484. though supporting the required events and at least a subset of the Core 
  1485. event suite will buy you a lot of functinality from within AppleScript.  
  1486. Especially important are the Get Current Selection and Set Current 
  1487. Selection events (which are really Get/Set Data on the contents of the 
  1488. current selection of the application)
  1489.  
  1490. The signature for your application SHOULD be registered with DTS to avoid 
  1491. conflicts; this is done through e-mail to DEVSUPPORT@AppleLink.Apple.Com 
  1492. and the form you use is located on the developer CDs and found on 
  1493. ftp.apple.com.
  1494.  
  1495. 8.4) Q: How do AppleEvents interface with AppleScript? 
  1496.  
  1497. A: AppleEvents are the meat and potatoes of AppleScript.  If you support 
  1498. the AppleEvent Object Model from within your application, users can 
  1499. control you through AppleScript.
  1500.  
  1501. The first thing you should do is get ahold of Inside Mac: 
  1502. Interapplication Communication, and a copy of the AppleEvents Registry.  
  1503. The former tells you all you ever need to know about AppleEvents, while 
  1504. the latter is paramount for implementing the right standard events.  If 
  1505. everybody use the standard events, dynamic data interchange between any 
  1506. applications will become sweet reality!
  1507.  
  1508. Then there is the 'aete' resource which lets you put names on the events 
  1509. you support, so that users can "Open Terminology" on your application 
  1510. from within the Apple Script Editor and use the proper AppleScript 
  1511. commands in their scripts.  The format of an aete resource is defined in 
  1512. Inside Macintosh: Interapplication Communication.
  1513.  
  1514. 8.5) Q: Can I compile and run scripts from within my application?
  1515.  
  1516. A: Yes, this is very simple.  There are toolbox calls for reading 
  1517. scripts, compiling scripts, and executing scripts.  (OSACompile, 
  1518. OSAExecute) These are all documented in Inside Mac: Interapplication 
  1519. Communication.
  1520.  
  1521. 8.6) Q: Is this a good way of getting a macro language almost 
  1522. for free? 
  1523.  
  1524. A: "Good" is an understatement.  Just let users write scripts, load them 
  1525. into menu items and go.  Total systems integration in under a week, 
  1526. including adding support for the AEOM to your application.
  1527.  
  1528. There is source code for an application called "MenuScripter" on the 
  1529. developer CD which shows you how to do an application with all of the 
  1530. menus being AppleScript scripts.
  1531.  
  1532. 8.7) Q: Why do I get error -903 (noPortErr) when I try to send an Apple 
  1533. Event?
  1534.  
  1535. A: Make sure the isHighLevelEventAware flag in your application's SIZE 
  1536. resource is set.  The AE Manager won't allow you to send events if you're 
  1537. not able to receive them.
  1538.  
  1539. *9* Standalone Code and Linking
  1540.  
  1541. 9.1) Q: I've got a resource with code in it off in limboland (sometimes 
  1542. called the resource fork) and I want to open it...  what do I do? A: You 
  1543. open the file you have the code resource in, load the resource and lock 
  1544. it high (don't unlock it first, since someone else may be using it).  
  1545. Then you cast the handle to a function pointer, and call it normally.
  1546.  
  1547. Suppose your code resource is compiled as a SACD id 128, and is 
  1548. defined as: 
  1549.  
  1550. *code*
  1551. long
  1552. main ( MyParams * params ) {
  1553.         switch ( params -> message ) {
  1554.         case messageInit :
  1555.                 return init ( params ) ;
  1556.         ...
  1557.         }
  1558.         return 0L ;
  1559. }
  1560. *end*
  1561.  
  1562. Also suppose you already have the vRefNum, parID and name of the 
  1563. resource file you want to use. Do this: 
  1564.  
  1565. *code*
  1566.         setup_paramblock ( & the_params ) ;
  1567.         the_params . message = messageInit ;
  1568.         refNum = HOpenResFile ( vRefNum , parID , name , fsRdPerm ) ;
  1569.         if ( refNum < 1 ) {
  1570.                 fail ( ResError ( ) ) ;
  1571.         }
  1572.         the_code = GetResource ( 'SACD' , 128 ) ;
  1573.         HLockHi ( the_code ) ;
  1574.         retval = ( * ( ( long ( * ) ( MyParams * ) ) StripAddress ( * the_code ) ) ) ( & the_params ) ;
  1575.         ...
  1576. *end*
  1577.  
  1578. The StripAddress is important; if your app is running in 24bit 
  1579. mode, the resource handle may contain tag bits and you don't 
  1580. want strange things to happen if the code resource switches into 
  1581. 32bit mode (which QuickDraw may do, incidentally)
  1582.  
  1583. Exactly how you structure your calling conventions is up to you; 
  1584. there is no accepted standard (except for HyperCard XCMDs, but 
  1585. that is probably overkill for you). 
  1586.  
  1587. *10* Compatibility
  1588.  
  1589. 10.1) Q: I see all these people call Gestalt without first 
  1590. checking whether it's implemented. Isn't that bad? 
  1591.  
  1592. A: No; Gestalt and a few other traps (the HXxx file manager 
  1593. traps, and FindFolder) are implemented using glue so they do the 
  1594. right thing even if the trap is not implemented. 
  1595.  
  1596. If you want to get rid of the glue, you can #define 
  1597. SystemSevenOrLater (and, using Think C/C++, re-pre-compile 
  1598. MacHeaders) However, then you will be responsible for checking 
  1599. for these features before you use them. 
  1600.  
  1601. 10.2) Q: What more functions are implemented in glue? 
  1602.  
  1603. A: Wake Up and Smell the Glue!
  1604.  
  1605. How often have you wished you could use that cool new ToolBox 
  1606. call, but didn't want to make your application System 7 
  1607. dependent? Well, it might be that you *could* in fact have used 
  1608. the call. Several traps are implemented in glue, that is, much 
  1609. of their functionality is linked into your application and thus 
  1610. available even if you are running under an old System. 
  1611.  
  1612. This list applies to MPW 3.2 and should also be valid for the 
  1613. current version of Think C. If you find any inaccuracies, please 
  1614. report them to me. (neeri@iis.ee.ethz.ch) 
  1615.  
  1616. FSOpen: Tries first OpenDF, then Open. 
  1617.  
  1618. HOpenResFile: Full functionality emulated if trap not available 
  1619.  
  1620. HCreateResFile: Full functionality emulated if trap not 
  1621. available 
  1622.  
  1623. FindFolder: Under System 6, understands the following values for 
  1624. folderType and returns the System Folder for all of them: 
  1625.  
  1626. kAppleMenuFolderType 
  1627.  
  1628. kControlPanelFolderType 
  1629.  
  1630. kExtensionFolderType 
  1631.  
  1632. kPreferencesFolderType 
  1633.  
  1634. kPrintMonitorDocsFolderType 
  1635.  
  1636. kStartupFolderType 
  1637.  
  1638. kSystemFolderType 
  1639.  
  1640. kTemporaryFolderType 
  1641.  
  1642. SysEnvirons: Full functionality emulated if trap not available 
  1643.  
  1644. NewGestalt: Returns an error if not implemented 
  1645.  
  1646. ReplaceGestalt: Returns an error if not implemented 
  1647.  
  1648. Gestalt: The following selectors are always implemented: 
  1649.  
  1650. vers    mach    sysv    proc    fpu     
  1651.  
  1652. qd      kbd     atlk    ram     lram    
  1653.  
  1654. 10.3) Q: I have to support System 6, don't I? 
  1655.  
  1656. A: It would be foolish to lock yourself out of the many benefits 
  1657. the System 7 API provides for software that you start to write 
  1658. now. Some of the System 6 and older things (likely SFGetFile and 
  1659. wdRefNums among others) will be phased out of the interfaces and 
  1660. lose support; especially on future platforms. 
  1661.  
  1662. The installed base of System 7 is larger than that of System 6; 
  1663. this is not surprising because Apple has been shipping System 7 
  1664. for several years with all new machines, including the LCII, 
  1665. Classic II, Performas and Color Classic. Another argument is 
  1666. that newer computer owners (having System 7) are much more 
  1667. likely to buy new software than old computer owners who have 
  1668. systems that already do what they want them to. 
  1669.  
  1670. The added work to support both System 6 and System 7 is 
  1671. significant; if you have the time and money you may want to do 
  1672. it, but only supporting System 6 and not System 7 is doomed to 
  1673. fail in the market of today. 
  1674.  
  1675. Some may call this position subjective; I call it business sense 
  1676. based on market demographics. A rule of thumb may be that if you 
  1677. target color machines only, you can just as well demand System 7 
  1678. as well. 
  1679.  
  1680. 10.4) Q: Why does my application work on an SE with accellerator 
  1681. (or a Mac II or Quadra), but not on one without? 
  1682.  
  1683. A: Assuming you're not calling Color QuickDraw (which is not 
  1684. available on accellerated SEs), you most probably have an 
  1685. odd-aligned word access somewhere. 
  1686.  
  1687. The 68000 does not allow words or longwords to be read from odd 
  1688. addresses, while the 68020 and up relaxes this restriction (it 
  1689. still is slower than aligned-word access though) 
  1690.  
  1691. This may or may not crash depending on your compiler: 
  1692.  
  1693. *code*
  1694. struct foo {
  1695.         char c1 ;
  1696.         char c2 ;
  1697.         char c3 ;
  1698.         char c4 ;
  1699.         char c5 ;
  1700. } bar ;
  1701.  
  1702.         long * x = ( long * ) & bar . c2 ;
  1703.         * x = 0x12345678 ; /* X is odd if compiler doesn't pad */
  1704.  
  1705. This WILL crash on an SE/Plus/Classic/PB100:
  1706.  
  1707. char foo [ 10 ] ;
  1708.  
  1709.         long * x = ( long * ) & foo [ 1 ] ;
  1710.         * x = 0x12345678 ;
  1711.  
  1712. *end*
  1713.  
  1714. 10.5) Q: Why does my application work on a IIci but not on a 
  1715. Quadra? 
  1716.  
  1717. A: Two reasons: 
  1718.  
  1719. 1) The Quadras 900 and 950 have special processors that handle the serial 
  1720. ports; if you write directly to the serial chips, you will crash (this 
  1721. goes for the IIfx as well)
  1722.  
  1723. 2) The Quadras have 68040 processors, as have the Centrises.  These 
  1724. processors have separate instruction and data caches (like the 68030) but 
  1725. they are larger (4K each) and unlike the 68030 which is write-through 
  1726. data cached, the 68040 is copy-back data cached.  This means that changes 
  1727. you make to "your code" aren't really changed all the time, since the 
  1728. changes may still be in the data cache and not written to memory when the 
  1729. CPU reads that part of memory into its I-cache.  Even worse; that part 
  1730. might already have been read into the I-cache before you change it in the 
  1731. D-cache, meaning that writing out the D-cache will still not be enough.  
  1732. You need to flush both the caches when writing self-modifying code.
  1733.  
  1734. Self-modifying code includes code that builds its own jump tables and 
  1735. code that decrypts itself and code that "stubs" MDEFs or WDEFs to jump 
  1736. back into the application code.
  1737.  
  1738. You flush the cache using FlushDataCache() which is implemented if 
  1739. Gestalt says you have a 68020 or better processor (or if the _HwDispatch 
  1740. trap is implemented)
  1741.  
  1742. 10.6) Q: Why does my application work on my Quadra but not on my 
  1743. accellerated SE?
  1744.  
  1745. A: You're probably calling Color QuickDraw without first checking if it's 
  1746. available.  The following machines do not have color QuickDraw in ROM nor 
  1747. RAM:
  1748.  
  1749. Mac Plus, Mac SE, Mac Classic, Mac Luggable, PowerBook 100, Outbound
  1750.  
  1751. 10.7) Q: I do check for color quickdraw, but crash nevertheless. 
  1752.  
  1753. A: _Gestalt lies under some versions of System 7; it says that non-color 
  1754. machines HAVE color QuickDraw when you test using the 
  1755. gestaltQuickdrawFeatures selector.
  1756.  
  1757. Instead, check the gestaltQuickdrawVersion selector, if it returns >= 
  1758. gestalt8BitQuickdraw then you can safely use gestaltQuickdrawFeatures, 
  1759. else you only have b/w QuickDraw.
  1760.  
  1761. 10.8) Q: Why are there no C/C++ compilers that optimize for the Mc68040?
  1762.  
  1763. A: Beats me; optimizing for the 68040 can make programs up to 50% faster 
  1764. on that chip while still losing nothing, or very little (less than 10%) 
  1765. on older chips.
  1766.  
  1767. *11* Optional System Software
  1768.  
  1769. 11.1 - QuickTime
  1770. 11.1.1) Q: I want to write a Amiga QuickTime player and need the 
  1771. CODEC format details. 
  1772.  
  1773. A: Although the structure of QuickTime movies is well documented in 
  1774. Inside Mac: QuickTime, the inner workings of the Apple compression 
  1775. modules is a trade secret that Apple will only license to you at great 
  1776. cost.  Perhaps it's time for a freeware, cross-platform QuickTime codec?
  1777.  
  1778. *12* Third-Party Solutions
  1779.  
  1780. 12.1) Q: What are some royalty-free databases available for the 
  1781. Macintosh?
  1782.  
  1783. These are commercial, but with no run-time licenses:
  1784.  
  1785. Prograph CPX comes with a database that can do indexes and tables.  
  1786. <sales@prograph.ca>
  1787.  
  1788. C-Index Pro is an engine that comes with source, does tables and indexes 
  1789. in one compound file.  <triosystems@applelink.apple.com>
  1790.  
  1791. dtF is a relational database library.  <DTF.AMERICA@applelink.apple.com>
  1792.  
  1793. NeoAccess is an object-oriented database, where you can store objects and 
  1794. retrieve by field value; it handles inheritance as well.  <comes as a 
  1795. demo on the CodeWarrior CD with an unlockable archive of the real thing>
  1796.  
  1797. *13* Dessert
  1798.  
  1799. 13.1) Q: Dessert? 
  1800.  
  1801. A: Honey Hill Farms Cookie Jar Frozen Yoghurt or Haagen-Dazs Raspberry & 
  1802. Cream Ice Cream.
  1803.  
  1804. Hokey-Pokey icecream with chocolate sauce and (for those who like their 
  1805. brain food firmer) Almond and Double Chocolate CookieTime cookies!?
  1806.  
  1807. [recipes, anyone?]
  1808.  
  1809. *14* Contributors
  1810.  
  1811. This is obviously an incomplete list as far as it reflects pre-10/31/94 
  1812. submissions, but I will credit new submissions to the best of my 
  1813. ability.
  1814.  
  1815. Denis Birnie
  1816. Scott Bronson <urge@mcl.mcl.ucsb.edu>
  1817. Bruce Hoult <Bruce@hoult.actrix.gen.nz>
  1818. Matthias Neeracher
  1819. Eric Slosser <slosser@apple.com>
  1820. Chris Thomas <thunderone@delphi.com>
  1821. Jon W..atte <h+@nada.kth.se>
  1822. -- 
  1823.  -- Jon W{tte, h+@nada.kth.se, Mac Software Engineer Deluxe --
  1824.     
  1825. "Smart Friends ask no SCSI questions!"
  1826.     Ñ Apple employee at the Bash
  1827.  
  1828.